Skip to content

ConstraintAnalysis: Handle x == C || { x > C && x <= D }#8933

Closed
kripken wants to merge 70 commits into
WebAssembly:mainfrom
kripken:compar.b
Closed

ConstraintAnalysis: Handle x == C || { x > C && x <= D }#8933
kripken wants to merge 70 commits into
WebAssembly:mainfrom
kripken:compar.b

Conversation

@kripken

@kripken kripken commented Jul 23, 2026

Copy link
Copy Markdown
Member

This is common in loops, where there is an initial value and the branch
back to the loop top has a bounded incremented value. The OR of such
a case is x >= C && x <= D, that is, the x == C fuses with x > C.

To make this and further things nice to write, add a Matcher utility.

@kripken
kripken requested a review from tlively July 23, 2026 22:29
@kripken
kripken requested a review from a team as a code owner July 23, 2026 22:29
Comment thread src/ir/constraint.cpp
Comment on lines +261 to +264
// As a convenience, allow using the object instead of the pointer.
Term& operator[](Var& var) {
return std::unordered_map<Var*, Term>::operator[](&var);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not seem worth defining a subtype of std::unordered_map for.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moot point, but look how pretty it makes the final matching code 😄 Not a single wasted character, not even a &

Comment thread src/ir/constraint.cpp
Comment on lines +373 to +381
// Simple range fusing, add an equality to turn > into >= :
//
// { x == A } || { x > A && x <= B } , A < B ==> { x >= A && X <= B }
//
// (A < B is required to avoid a contradiction on the right)
Var A, B;
if (auto result = Matcher({{Eq, A}}, {{GtS, A}, {LeS, B}})
.require(A, LtS, B)
.checkUnordered(self, other)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me that we need this kind of global view on the constraints and all the complexity that brings. We should be able to define an or operation of individual constraints so that e.g. (x == A) ⊔ (x > A) = (x >= A). Then ORing a constraint into a constraint set would just be 1) iterate the constraint set to look for contradictions with the new constraint, and 2) iterate the constraint set looking for constraints that can be merged with the new constraint without becoming the top constraint.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, yeah, I had a related thought on a walk a took now. ORing can never generate a new contradiction, by definition - so my caution in this PR is not really needed. So, yes, I think I can make us look at individual constraints here, as you wrote (but 1 is not needed, only 2).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, a case that does require a more global view is (x == A) \/ (x == B), where this should become (x >= A) /\ (x <= B) if we know A < B (or similar for A > B). But this can still be handled locally by doing an in-place update of (x == A) to (x >= A) and then doing an approximate AND with (x <= B).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that needs a little more reasoning, but we can still do it with a simple peephole optimization, I think.

@kripken

kripken commented Jul 24, 2026

Copy link
Copy Markdown
Member Author

Replaced by #8936

@kripken kripken closed this Jul 24, 2026
@kripken
kripken deleted the compar.b branch July 24, 2026 17:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants